package com.aptemo.webetek.client.widgets.games;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import com.aptemo.webetek.client.WebetekUserServiceAsync;
import com.aptemo.webetek.client.commands.GotAsynchCallback;
import com.aptemo.webetek.client.commands.impl.AddLabelAction;
import com.aptemo.webetek.client.commands.impl.AssignResultAction;
import com.aptemo.webetek.client.commands.impl.CreateEventAction;
import com.aptemo.webetek.client.commands.impl.DeleteEventAction;
import com.aptemo.webetek.client.commands.impl.GetEventDetailsAction;
import com.aptemo.webetek.client.commands.impl.GetLabelsAction;
import com.aptemo.webetek.client.commands.impl.ModifyGameAction;
import com.aptemo.webetek.client.commands.responses.GotAddLabelCallback;
import com.aptemo.webetek.client.commands.responses.GotLabelsList;
import com.aptemo.webetek.client.commands.responses.ResponseStatus;
import com.aptemo.webetek.client.enums.EEditMode;
import com.aptemo.webetek.client.enums.EnumEventStatus;
import com.aptemo.webetek.client.enums.EnumUserRole;
import com.aptemo.webetek.client.events.DecisionEvent;
import com.aptemo.webetek.client.events.DecisionHandler;
import com.aptemo.webetek.client.events.GameListUpdatedEvent;
import com.aptemo.webetek.client.events.HasDecisionHandlers;
import com.aptemo.webetek.client.events.ResultAssignedEvent;
import com.aptemo.webetek.client.events.TeamUpdatedEvent;
import com.aptemo.webetek.client.exceptions.BackendException.EErrorCodes;
import com.aptemo.webetek.client.mvp.BaseDisplay;
import com.aptemo.webetek.client.mvp.BasePresenter;
import com.aptemo.webetek.shared.EventBean;
import com.aptemo.webetek.shared.LabelBean;
import com.aptemo.webetek.shared.PickBean;
import com.aptemo.webetek.shared.UserBean;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.event.dom.client.HasClickHandlers;
import com.google.gwt.event.shared.HandlerManager;
import com.google.gwt.user.client.ui.HasText;
import com.google.gwt.user.client.ui.HasValue;
import com.google.gwt.user.client.ui.HasWidgets;

public class GameResumePresenter implements BasePresenter, ClickHandler, DecisionHandler
{

	public interface Display extends BaseDisplay
	{
		HasText getTitleField();

		HasText getNameField();

		HasText getDescField();

		HasValue<Date> getDateField();

		HasClickHandlers getSaveBtn();

		// HasClickHandlers getDeleteBtn();

		HasText getInfoField();

		// HasChangeHandlers getBetTypeList();

		void setPicksData(List<String> picks);

		HasText getPicksField();

		void setLabels(ArrayList<LabelBean> result);

		void setSelectedLabel(String id);

		HasText getNewLabelTextBox();

		void addLabel(LabelBean label);

		String getSelectedLabel();

		// EnumEventType getSelectedBetType();

		void setResult(EventBean bet);

		HasText getResultCommentField();

		String getResultPickValue();

		String getSelectedResult();

		HasDecisionHandlers getResultsConfirmation();

		HasDecisionHandlers getNewLabelConfirmation();

		// void setBetType(EnumEventType betType);

		void setEditMode(EEditMode mode, boolean resultsLinkVis);

		HasDecisionHandlers getDeleteConfirmation();

		void hideResultsConfirmationDialog();

		void hideNewLabelConfirmationDialog();

		void hideDeleteConfirmationDialog();

		String translate(String string);
	}

	private HandlerManager			eventBus;
	private Display					display;
	private WebetekUserServiceAsync	rpcService;
	private String					eventId;
	private String					teamId;
	private EventBean				eventBean;
	protected UserBean				currentUser;
	private ArrayList<String>		labels;

	public GameResumePresenter(UserBean user, Display view, HandlerManager eventbus, WebetekUserServiceAsync rpc, String id, String teamId)
	{
		this.eventBus = eventbus;
		this.rpcService = rpc;
		this.eventId = id;
		this.teamId = teamId;
		this.currentUser = user;
		display = view;
	}

	@Override
	public void go(HasWidgets container)
	{
		container.clear();
		bind();

		container.add(display.getDisplay());

		if ((null != eventId) && (!eventId.isEmpty()))
		{
			loadData();
		}
		else
		{
			ArrayList<String> picks = new ArrayList<String>();
			display.setPicksData(picks);
			display.setEditMode(EEditMode.EADD, false);
			display.getDateField().setValue(new Date());

			loadLabels();
		}

	}

	@Override
	public void onClick(ClickEvent event)
	{
		if (event.getSource() == display.getSaveBtn())
		{
			ArrayList<PickBean> picks = new ArrayList<PickBean>();
			int index = 0;

			String items = display.getPicksField().getText();
			String[] tmp = items.split(",");
			for (int i = 0; i < tmp.length; i++)
			{
				String value = tmp[i].trim();
				PickBean pick = null;
				if (eventBean != null)
				{
					pick = eventBean.getPicks().get(index);
					pick.setTitle(value);
				}
				else
				{
					pick = new PickBean(value);
				}
				picks.add(pick);
				index++;
			}
			// while (!(item = display.getPickField(index).getText()).isEmpty())
			// {
			// PickBean pick = null;
			// if (data != null)
			// {
			// pick = data.getPicks().get(index);
			// pick.setTitle(item);
			// }
			// else
			// {
			// pick = new PickBean(item);
			// }
			// picks.add(pick);
			// index++;
			// }

			display.getInfoField().setText(display.translate("saving"));

			if ((eventId == null) || (eventId.isEmpty()))
			{
				addGame(picks);
			}
			else
			{
				modifyGame(picks);
			}
		}

	}

	@Override
	public void onConfirmation(DecisionEvent event)
	{
		// common saving info...
		display.getInfoField().setText(display.translate("saving"));

		if (event.getSource() == display.getDeleteConfirmation())
		{
			deleteGame();
		}
		else if (event.getSource() == display.getNewLabelConfirmation())
		{
			newLabelConfirmation(event.getInfoField());
		}
		else if (event.getSource() == display.getResultsConfirmation())
		{
			resultConfirmation(event.getInfoField());
		}
	}

	private void bind()
	{

		display.getSaveBtn().addClickHandler(this);

		// display.getBetTypeList().addChangeHandler(new ChangeHandler()
		// {
		//
		// @Override
		// public void onChange(ChangeEvent event)
		// {
		// // int index = display.getSelectedItem(event);
		// EnumEventType ty = display.getSelectedBetType();
		//
		// // for add game resume only
		// if (betid == null)
		// {
		// //display.setBetType(ty);
		// ArrayList<String> picks = new ArrayList<String>();
		// for (int i = 0; i < ty.getValue(); i++)
		// {
		// picks.add("");
		// }
		// display.setPicksData(picks);
		//
		// }
		// }
		// });

		display.getNewLabelConfirmation().addDecisionHandler(this);

		display.getResultsConfirmation().addDecisionHandler(this);

		display.getDeleteConfirmation().addDecisionHandler(this);

	}

	private void loadData()
	{
		if ((null == eventId) || (eventId.isEmpty()))
		{
			return;
		}

		display.getInfoField().setText(display.translate("loading"));

		GetEventDetailsAction action = new GetEventDetailsAction(eventId);
		rpcService.invoke(action, new GotAsynchCallback<EventBean>()
		{

			@Override
			public void onError(String message, EErrorCodes code)
			{
				display.getInfoField().setText(message);
			}

			@Override
			public void onSuccess(EventBean bet)
			{
				eventBean = bet;

				display.getTitleField().setText(bet.getTitle());
				display.getNameField().setText(bet.getTitle());
				display.getDescField().setText(bet.getDescription());
				display.getDateField().setValue(bet.getDate());

				// display.setBetType(bet.getEventType());
				List<String> pickStrings = new ArrayList<String>();
				ArrayList<PickBean> picks = bet.getPicks();
				for (PickBean pick : picks)
				{
					pickStrings.add(pick.getTitle());
				}
				display.setPicksData(pickStrings);

				// and set created one
				labels = bet.getLabels();

				display.setResult(bet);

				display.getInfoField().setText("");

				loadLabels();

				// loadPlayerDetails();
				if (currentUser != null)
				{
					EnumEventStatus status = GameResumePresenter.this.eventBean.getStatus();
					boolean resultsLinkVis = status == EnumEventStatus.ACTIVE ? false : true;
					EnumUserRole role = currentUser.getRole();
					EEditMode mode = (role == EnumUserRole.EDITOR) || (role == EnumUserRole.ADMIN) ? EEditMode.EEDIT : EEditMode.EREADONLY;
					display.setEditMode(mode, resultsLinkVis);
				}

			}
		});
	}

	// private void loadPlayerDetails()
	// {
	// //
	// GetPlayerDetailsAction action = new GetPlayerDetailsAction("", teamId);
	// rpcService.invoke(action, new GotAsynchCallback<UserBean>()
	// {
	//
	// @Override
	// public void onError(String message, EErrorCodes code)
	// {
	// display.getInfoField().setText(message);
	// }
	//
	// @Override
	// public void onSuccess(UserBean result)
	// {
	// EnumRole role = result.getRole();
	//
	// EEditMode mode = (role == EnumRole.EDITOR) || (role == EnumRole.ADMIN) ?
	// EEditMode.EEDIT : EEditMode.EREADONLY;
	//
	// EnumBetStatus status = GameResumePresenter.this.data.getStatus();
	// boolean resultsLinkVis = status == EnumBetStatus.ACTIVE ? false : true;
	//				
	// display.setEditMode(mode, resultsLinkVis);
	// }
	// });
	//
	// }

	private void loadLabels()
	{
		GetLabelsAction ac = new GetLabelsAction(teamId);
		rpcService.invoke(ac, new GotLabelsList()
		{

			@Override
			public void onError(String message)
			{
				// TODO Auto-generated method stub

			}

			@Override
			public void got(ArrayList<LabelBean> result)
			{
				display.setLabels(result);

				// get the selected labels...
				if ((labels != null) && (!labels.isEmpty()) && (labels.size() > 0))
				{
					// TODO take the first one for now
					display.setSelectedLabel(labels.get(0));
				}

			}
		});

	}

	private void addGame(ArrayList<PickBean> picks)
	{
		String labelid = display.getSelectedLabel();

		CreateEventAction action = new CreateEventAction(teamId, labelid, display.getNameField().getText(), display.getDescField().getText(), display
				.getDateField().getValue(), picks);

		rpcService.invoke(action, new GotAsynchCallback<EventBean>()
		{

			@Override
			public void onError(String message, EErrorCodes code)
			{
				display.getInfoField().setText(message);
			}

			@Override
			public void onSuccess(EventBean bet)
			{
				// refresh games
				display.getInfoField().setText(display.translate("addSuccess"));
				// refresh entire team data..
				eventBus.fireEvent(new GameListUpdatedEvent(teamId, bet.getKey()));
			}
		});
	}

	private void modifyGame(ArrayList<PickBean> picks)
	{
		// Get selected label
		String label = display.getSelectedLabel();
		ArrayList<String> sellabels = new ArrayList<String>();
		if (!label.isEmpty())
		{
			sellabels.add(label);
		}

		Date date = display.getDateField().getValue();
		// date.setTime(time.getTime());

		// create bean object...
		EventBean bet = new EventBean(date, display.getNameField().getText(), display.getDescField().getText());
		bet.setKey(eventId);
		bet.setPicks(picks);
		bet.setLabels(sellabels);

		ModifyGameAction action = new ModifyGameAction(bet, teamId);
		rpcService.invoke(action, new GotAsynchCallback<EventBean>()
		{

			@Override
			public void onError(String message, EErrorCodes code)
			{
				display.getInfoField().setText(message);
			}

			@Override
			public void onSuccess(EventBean bet)
			{
				// show games
				display.getInfoField().setText(display.translate("modifySuccess"));
				eventBus.fireEvent(new GameListUpdatedEvent(teamId));
			}
		});
	}

	private void deleteGame()
	{

		DeleteEventAction action = new DeleteEventAction(eventId);

		// TODO what to do in case of error...
		rpcService.invoke(action, new GotAsynchCallback<ResponseStatus>()
		{

			@Override
			public void onSuccess(ResponseStatus status)
			{
				display.hideDeleteConfirmationDialog();
				display.getInfoField().setText(display.translate("deleteSuccess"));

				// TODO close window
				eventBus.fireEvent(new GameListUpdatedEvent(teamId));
			}

			@Override
			public void onError(String message, EErrorCodes code)
			{
				display.getInfoField().setText(message);
			}
		});
	}

	private void newLabelConfirmation(HasText info)
	{
		AddLabelAction action = new AddLabelAction(display.getNewLabelTextBox().getText(), teamId);
		rpcService.invoke(action, new GotAddLabelCallback()
		{

			@Override
			public void onError(String message)
			{
				display.getInfoField().setText("Error: " + message);
			}

			@Override
			public void got(LabelBean label)
			{
				display.hideNewLabelConfirmationDialog();

				// reload labels...
				display.addLabel(label);
				display.getInfoField().setText(display.translate("labelCreated"));

				// refresh team data
				eventBus.fireEvent(new TeamUpdatedEvent(teamId));
			}
		});
	}

	private void resultConfirmation(final HasText info)
	{
		String comment = display.getResultCommentField().getText();
		String pickid = display.getResultPickValue();

		AssignResultAction action = new AssignResultAction(teamId, eventId, pickid, comment);
		rpcService.invoke(action, new GotAsynchCallback<EventBean>()
		{

			@Override
			public void onError(String message, EErrorCodes code)
			{
				info.setText(message);
			}

			@Override
			public void onSuccess(EventBean result)
			{
				display.hideResultsConfirmationDialog();
				display.getInfoField().setText(display.translate("resultSuccess"));

				eventBus.fireEvent(new ResultAssignedEvent(teamId));
			}
		});
	}

}
